package ph.com.gs3.formalistics.service.services;

import java.util.List;

import ph.com.gs3.formalistics.global.utilities.logging.FLLogger;
import ph.com.gs3.formalistics.global.utilities.services.ServiceEventNotifierUtility;
import ph.com.gs3.formalistics.model.communicators.CommentCommunicatorModule;
import ph.com.gs3.formalistics.model.communicators.HttpCommunicator;
import ph.com.gs3.formalistics.model.dao.CommentsDAO;
import ph.com.gs3.formalistics.model.dao.UserAccountsDAO;
import ph.com.gs3.formalistics.model.valueobjects.business.Comment;
import ph.com.gs3.formalistics.model.valueobjects.business.User;
import ph.com.gs3.formalistics.presenter.MainActivity;
import ph.com.gs3.formalistics.service.managers.CommentManager;
import ph.com.gs3.formalistics.service.managers.CommentManager.CommentSaveFailedException;
import ph.com.gs3.formalistics.service.managers.CommentManager.SubmitCommentFailedException;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;

public class OutgoingCommentsSubmitService extends IntentService {

	public static final String TAG = OutgoingCommentsSubmitService.class.getSimpleName();
	public static final String NAME = OutgoingCommentsSubmitService.class.getName();

	public static final String ACTION_ON_SERVICE_STARTED = NAME + "_on_service_started";
	public static final String ACTION_ON_SUBMIT_FAILED = NAME + "_on_submit_failed";
	public static final String ACTION_ON_COMMENT_SUBMITTED = NAME + "_on_comment_submitted";
	public static final String ACTION_ON_SERVICE_DONE = NAME + "_on_service_done";

	public static final String EXTRA_CURRENT_USER = "current_user";
	public static final String EXTRA_SUBMITTED_COMMENT = "submitted_comment";
	public static final String EXTRA_SUBMIT_FAILED_COMMENT = "submit_failed_comment";
	public static final String EXTRA_SUBMIT_FAILED_EXCEPTION = "submit_failed_exception";

	private CommentsDAO commentsDAO;
	private CommentManager commentManager;

	public OutgoingCommentsSubmitService() {
		super(TAG);
	}

	@Override
	protected void onHandleIntent(Intent intent) {

		Bundle extras = intent.getExtras();
		User currentUser = (User) extras.getSerializable(EXTRA_CURRENT_USER);

		// notify
		Bundle notificationExtras = new Bundle();
		notificationExtras.putSerializable(MainActivity.EXTRA_LOGGED_IN_USER, currentUser);
		ServiceEventNotifierUtility.getDefaultInstance().displayNotificationWithProgress(this,
		        ServiceEventNotifierUtility.NOTIFICATION_ID_PRIMARY,
		        "Sending your outgoing comments", 0, 0, true, notificationExtras);

		String server = currentUser.getAccountServer();
		String userWebId = Integer.toString(currentUser.getWebId());

		initializeManager(server);

		broadcastServiceStarted();

		// get comments to submit
		commentsDAO.open();
		List<Comment> comments = commentsDAO.getAllOutgoingComments(server, userWebId);
		commentsDAO.close();

		for (Comment comment : comments) {

			FLLogger.d(TAG, "Submitting comment: " + comment.getDbId() + " " + comment.getText());

			Comment submittedComment;
			try {
				submittedComment = commentManager.submitOutgoingComment(comment);
				broadcastCommentSubmitted(submittedComment);
			} catch (SubmitCommentFailedException | CommentSaveFailedException e) {
				broadcastCommentSubmitFailed(e, comment);
				// TODO inform UI for every failure here
				e.printStackTrace();
			}

		}

		ServiceEventNotifierUtility.getDefaultInstance().dismissPrimaryNotification(this);

		broadcastServiceDone();

	}

	private void initializeManager(String server) {

		UserAccountsDAO userAccountsDAO = new UserAccountsDAO(getApplicationContext());
		commentsDAO = new CommentsDAO(getApplicationContext());

		HttpCommunicator communicator = new HttpCommunicator();
		CommentCommunicatorModule commentCommunicatorModule = new CommentCommunicatorModule(
		        communicator, server);

		commentManager = new CommentManager(userAccountsDAO, commentsDAO, commentCommunicatorModule);

	}

	// =========================================================================================
	// {{ Broadcast Methods

	private void broadcastServiceStarted() {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(ACTION_ON_SERVICE_STARTED);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		sendBroadcast(broadcastIntent);

	}

	private void broadcastServiceDone() {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(ACTION_ON_SERVICE_DONE);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		sendBroadcast(broadcastIntent);

	}

	private void broadcastCommentSubmitted(Comment comment) {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(ACTION_ON_COMMENT_SUBMITTED);
		broadcastIntent.putExtra(EXTRA_SUBMITTED_COMMENT, comment);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		sendBroadcast(broadcastIntent);

	}

	private void broadcastCommentSubmitFailed(Exception exception, Comment failedComment) {

		Intent broadcastIntent = new Intent();

		broadcastIntent.setAction(ACTION_ON_SUBMIT_FAILED);
		broadcastIntent.putExtra(EXTRA_SUBMIT_FAILED_COMMENT, failedComment);
		broadcastIntent.putExtra(EXTRA_SUBMIT_FAILED_EXCEPTION, exception);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		sendBroadcast(broadcastIntent);

	}

	// }}

}
